<?php
/**
 * --------------------------------------------------
 * USER API
 * blah blah blah
 * blah blah blah
 * blah blah blah
 *
 * @author quocnguyen@clgt.vn
 * @version 1.0
 * @copyright clgt
 * @link http://clgt.vn
 * --------------------------------------------------
 */

class Api_User extends Api {

	private $user;
	private $role;
	function __construct()
	{
		parent::__construct();
		$this->user = UserTable::getInstance();
		$this->role = RoleTable::getInstance();
	}
	//----------------CRUD FUNCTION----------------------//
	
	/**
	 * CRUD
	 */
	public function create($user_info = array())
	{
		$user = new User();

		// chi lay du thong tin can thiet
		$params = Arr::extract($user_info, array(
				'first_name', 'last_name', 'username', 'email', 'password'
			));
		$user->setArray($params);
		if ($user->isValid())
		{
			$user->save();
			return TRUE;
		}
		else
		{
			return $user->getErrorStack()->toArray();
		}
		
	}

	/**
	 * CRUD
	 */
	public function read($param)
	{		

		if (is_numeric($param))
		{
			$user = $this->user->findOneById($param);
		}
		else
		{
			$user = $this->user->findOneByName($param);
		}
		
		return $user;
	}

	/**
	 * CURD
	 */
	public function update(int $user_id, array $user_info)
	{
		$user = $this->read($user_id); 
		$user->setArray($user_info);
		$user->save();

	}

	/**
	 * CRUD
	 */
	public function delete(int $user_id)
	{
		return $this->update($user_id, array(
			'is_deleted' => TRUE,
		));
		
	}

	public function get_all()
	{
		return $this->user->findAll();
	}
	//--------------- END CRUD------------------------//

	/**
	 * 
	 */
	public function login_required()
	{
		if (! $this->is_logged())
		{
			
		}
	}

	/**
	 * kiểm tra user có đang đăng nhập hay không
	 * nếu có role thì kiểm tra luôn user có quyền hay ko ?
	 */
	public function is_logged($roles = NULL)
	{
		$user_info = Session::instance()->get('user');

		// neu ko co dang nhap, thoat ngay.
		if (is_null($user_info))
			return FALSE;	

		// neu co dang nhap, role ko can kiem tra, TRUE
		if (is_null($roles))
			return TRUE;
		

		if (isset($user_info['roles']))
		{
			return $this->has_role($user_info['id'], $roles);

		}
	
	}

	/**
	 * 
	 */
	public function get_user_info()
	{
		$user_info = array();
		if ($this->is_logged())
		{
			$user_info = Session::instance()->get('user');
		}
		return $user_info;
	}

	/**
	 * 
	 */
	public function login($param, $password, $role = NULL)
	{
		if ( ! isset($param) && ! isset($password))
		{
			return FALSE;
		}
		if (Valid::email($param))
		{
			return $this->_login_by_email($param, $password, $role);
		}
		else
		{
			return $this->_login_by_username($param, $password, $role);
		}
		
	}

	/**
	 * use in login
	 */
	private function _login_by_email($email, $password, $role_name)
	{		
		$q = Doctrine_Query::create()
			->select('*')
			->from('User u')
			->where('u.email = ?', $email)
			->andWhere('u.password = ?', $this->hash_password($password))
			->fetchOne();


		// neu tim thay
		if ($q !== FALSE)
		{
			$user_info = $q->toArray();
			foreach($q->Role as $role)
			{
				$role_list[] = array(
					'role_id' =>  $role->id,
					'role_name' => $role->role_name,
				);
			}

			// neu can xac thuc theo role.
			if ( ! is_null($role_name))
			{
				if ($this->has_role($q->id, $role_name))
				{
					return $this->_set_user_session($user_info, $role_list);		
				}
			}
			else
			{
				return $this->_set_user_session($user_info, $role_list);
			}
		}

		return FALSE;		
	}

	/**
	 * use in login
	 */
	private function _login_by_username($username, $password, $role)
	{
		$q = Doctrine_Query::create()
			->select('*')
			->from('User u')
			->where('u.username = ?', $username)
			->andWhere('u.password = ?', $this->hash_password($password))
			->fetchOne();
		
		// neu tim thay
		if ($q !== FALSE)
		{
			$user_info = $q->toArray();
			// neu can xac thuc theo role.
			if ( ! is_null($role_name))
			{
				if ($this->has_role($q->id, $role_name))
				{
					return $this->_set_user_session($user_info, $role_name);		
				}
			}
			else
			{
				return $this->_set_user_session($user_info);		
			}
		}

		return FALSE;
	}

	/**
	 * set all user info to session.
	 */
	private function _set_user_session($user_info, $role_name = NULL)
	{
		if ( ! is_null($role_name))
		{
			$user_info['roles']	 = $role_name;
		}

		return Kohana_Session::instance()->set('user', $user_info)->write();
		

	}

	public function logout()
	{
		// destroy session.
		return Kohana_Session::instance()->destroy();
	}

	/**
	 *  cộng tiền cho user.
	 */
	public function add_balance($user_id, $how_much)
	{
		
	}

	/**
	 * Check if user has role
	 * $roles  can be array of id, or name, or mixed.	 
	 * @param <int> user_id
	 * @param <mixed> $roles
	 */
	public function has_role($user_id, $roles)
	{
		
		if (is_array($roles))
		{
			foreach($roles as $role)
			{
				// chi can co 1 role false , return luon.
				if ($this->has_role($user_id, $role) === FALSE)
				{
					return FALSE;
				}
			}
		}
		else
		{
			$user = $this->read($user_id);
			if (is_numeric($roles))
			{
				foreach ($user->Role->toArray() as $list)
				{
					if ($list['role_id'] === $roles)
					{
						return TRUE;
					}
				}
				/// ko tim thay role_id nay
				return FALSE;

			}
			else
			{
				//echo $roles;
				//var_dump($user->Role->toArray());
				foreach ($user->Role->toArray() as $list)
				{
					if ($list['role_name'] === $roles)
					{
						return TRUE;
					}
				}
				// ko tim thay role name
				return FALSE;
			}
			
		}
		
		// user has all roles.
		return TRUE;
	}	

	/**
	 * remove role from user.
	 */
	public function remove_role($user_id, $role_id)
	{
		return TRUE;
	}

	/**
	 * Cấp cho user role mới.
	 */
	public function add_role($user_id, $params)
	{
		$user = $this->read($user_id);	
		// neu khong tim thay user nay, tra ve false
		if ($user === FALSE)	
		{
			return FALSE;
		}

		// co user, kiem tra bien params
		// neu params la array, thi add nhieu role.
		if (is_array($params))
		{
			foreach($params as $role)
			{
				$this->add_role($user_id, $role);
			}
		}
		else
		{
			if (is_numeric($params))
			{
				// neu params la role_id
				$role_id = $params;
				$role = $this->role->findOneById($role_id);				
				if ($role !== FALSE) 
				{
					$user->link('Role', $role->id);
				}
			}			
			else
			{	
				// neu params la role_name
				$role_name = $params;
				$role = $this->role->findOneByName($role_name);
				if ($role !== FALSE)
				{
					$user->link('Role', $role->id);
				}
			}
		}
		$user->save();
		
	}

	public function add_user_detail(int $user_id, array $user_info)
	{
		$user = $this->read($user_id);		
		return TRUE;
	}

	public function update_user_detail()
	{
		
	}


	/**
	 * hashpassword
	 */
	private function hash_password($password = NULL)
	{
		return md5($password);
	}

}